{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Aligning\n",
    "`align` is a module that can be used to align two different datasets. In particular, all three currently existing classes, namely `SignFlips`, regular `OrthogonalProcrustes`, and `SeedlessProcrustes` are aimed at correcting an orthogonal transformation of the data, the exact form of which is unknown. The motivation for this are orthogonal non-identifiabilities, which are common when dealing with various embedding methods, whether in statistical graphs or other domains. Noted that if two graphs are embedded using omnibus embedding - they don't need to be aligned."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Recall that an orthogonal matrix is any matrix $Q$ such that $Q^T Q = Q Q^T = I$. For all alignment methods, the main idea is to infer an orthogonal matrix $Q$ from the input data sets $X$ and $Y$, and subsequently use $Q$ in order to align $X$ to $Y$, by transforming $X$ as $\\hat{X} = X Q$. The major differences among classes in `align` come from the settings in which they are applicable, as well as additional assumptions made on the matrix $Q$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from graspologic.plot import heatmap\n",
    "from scipy.stats import special_ortho_group, ortho_group\n",
    "\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Simple rotation example\n",
    "\n",
    "First, let's build two simple datasets $X$ and $Y$, with all entries of $X$ coming from the $Uniform(0, 1)$ distribution, and $Y$ is a copy of $X$, and subsequently rotated around the origin, using the randomly generated matrix $Q$, displayed below:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "np.random.seed(314)\n",
    "X = np.random.uniform(0, 1, (15, 2))\n",
    "Q = special_ortho_group.rvs(2)\n",
    "Y = X @ Q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.94924938, -0.31452442],\n",
       "       [ 0.31452442, -0.94924938]])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 288x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "heatmap(Q, figsize=(4,4), vmin=-1, vmax=1)\n",
    "Q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots(1, 1, figsize=(6, 6))\n",
    "ax.set_title(\"Simple rotation example\")\n",
    "ax.scatter(X[:,0], X[:,1], label=r\"$X$\", marker='x')\n",
    "ax.scatter(Y[:,0], Y[:,1], label=r\"$Y$\", s=100, alpha=0.5)\n",
    "ax.set(xlim=(-1.20, 1.20), ylim=(-1.20, 1.20))\n",
    "ax.set_xticks([0])\n",
    "ax.set_yticks([0])\n",
    "ax.legend()\n",
    "ax.grid();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### SignFlips\n",
    "\n",
    "`SignFlips` assumes that $Q$ is not only orthogonal, but also diagonal, which constraints to matrices with $\\pm 1$ along the diagonal and $0$ everywhere else. In essence, it flips the dataset along some axes such that the two datasets end up in the same orthant (generalized quadrant). Which quadrant the dataset is \"located\" in is defined by some criterion, which is the dimension-wise medians by default. If the dataset needs to flip along some dimension, the corresponding entry in $Q$ will be $-1$, and $1$ otherwise."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "from graspologic.align import SignFlips\n",
    "aligner_SF = SignFlips() \n",
    "X_prime_SF = aligner_SF.fit_transform(X, Y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Since $X$ is entirely in the first quadrant, its dimension-wise medians in both dimensions are greater than $0$. Meanwhile $Y$ is predominantly in the third quadrant, so its dimension-wise medians are all smaller than $0$. Thus $X$ needs to be flipped both along the x-axis and y-axis in order for two datasets to arive to the same quandrant. So, the $Q_{SF}$ that the algorithm finds is"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-1,  0],\n",
       "       [ 0, -1]])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAQgAAADACAYAAAD4Ov2SAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy86wFpkAAAACXBIWXMAAAsTAAALEwEAmpwYAAANTElEQVR4nO3df4xlZ13H8fdnprvpajXbXdgSbOKGGgOlG8XWP1ooXZGagBZoSzSNQoXERGyNJBKJQgKN2mAsMZJUjFJDLQkasAtWa6TWtlahQaC6tqUFKRUNlLa73f7K0t2Z+frHvXfu8PT+mjtzZ2fo+5WcnJ1zznPOk03uJ9/nOefek6pCkgaZO9EdkLR5GRCShjIgJA1lQEgayoCQNNRJo3Zuf8XbvcUxY09+9toT3YXnhZN37MiJ7sNWZAUhaSgDQtJQBoSkoQwISUMZEJKGMiAkDWVASBrKgJA2SJLTk/xxkn9N8nSSSrJ/Fe3PSPKpJE8keSrJzUnOnF2PDQhpI/0IcBnwNHDrahom2QPcCewFLu+eZxdwR5LT17ebfSOfpJS0rv6lqvYAJHkT8IZVtH0XcCpwTlV9s3uOzwFfB94DvGN9u9phBSFtkKpaWkPzi4FbeuHQPd8h4CbgkrX2bRgDQlqlJEfGLet8vR3AGcA9A3YfBPZ0hyDrziGG1PjV7B33JcUnNqQjfacCAQ4P2Nfbtht4ZL0vbEBIq1RVO0/UpafcNzUDQmpsn9t03wx/nE4A7B6wb1d3Pai6WDMDQmpstoCoqqNJHgTOGrB7H/BoVa378AKcpJSeY/tcRi4nyAHgwiQv6m1Isgu4CLhxVhe1gpAa8zPMgCRv7v7zJ7vrC5K8AHimqv6he8ztwAVVtbIn1wBvAW5OchWwALy3u756Vv01IKTGtsy0SvhE8/f7u+v/ofOU5EBV9e0k59MJihvoVP93Aq+uqm+sfzc7DAipMcthRFMVDDtm/5DtXwXeuN59GsWAkBrzs60gthQDQmpstrsYJ5IBITUMiD4DQmrM8i7GVmNASA0riD4DQmoYEH0GhNRwiNFnQEgNK4g+A0JqbJvzK0o9BoTUiGOMZQaE1JjfPn+iu7BpGBBSY367Q4weA0JqxDmIZQaE1LCC6DMgpIZzEH0GhNSIz0EsMyCkhhVEnwEhNQyIPgNCasxvc5Kyx4CQGpk3IHoMCKnhbc4+A0JqOAfRZ0BIDW9z9hkQUsMKos+AkBpz2/xY9DgbIzXm5udGLtNKckqSDyX5VpKjSb6Q5A0TtHt/khqwPDx1ZyZkVEqNue0z+1gcAH4C+C3g68AvAweSXFRVN0/Q/kLg6RV/H1v3HjYMCKkxt23bup8zyeuB1wKXVNWB7rbbgJcAHwQmCYgvVNWRde/cCA4xpEbm50YuU7oYeAL4dG9DVRVwPfDSJGeuvefrzwpCasyPmaRMcmTcOapqZ7PpLOC+qlpqth9cuX/Mab+cZA/wCPB3wHuq6pFxfVkLA0JqzOguxm7gKwO2H16xf5ivAb8D3E1n3uGVdOYxfjrJ2VX1+Hp2dCUDQmqMG0YMqA4mVdPsq6obmk3/nOQu4DPAFcDvTdmfsQwIqTE/m7sYhxhcJezqrg8P2DdUVd2S5FvAuWvt2CgGhNSY0RDjXuDSJHPNPMS+7vqeKc45B7RzGuvKuxhSY0Z3MQ4AO4GLmu1vBR6oqnETlN/dx+RngNOAu6bt0CSsIKTG/Ayeg6DznMNtwHVJdtN5UOpy4FXAG3sHJbkduKCqsmLb3cBfAg8Ax4HzgHcB/w1cO4vO9hgQUmMWT1JWVSV5E3B1d9lJ57bmJVV105jm9wO/BrwY2Ab8L/AR4Hdn/eCUASE1ZvXinKp6Eriyuww7Zv+AbZfNpEMTMCCkxgy/i7Hl+D8hNeZOmskcxJZkQEgtA2KZASE1Mu8vSvUYEFLrpO0nugebhgEhNeIQY5kBIbXmHGL0GBBSwwqiz4CQGtnmHESPASG1ZvQk5VZkQEiNeBdjmQEhNZyD6DMgpJZ3MZYZEFIjs/k9iC3JgJBazkEsMyCkxqx+D2IrMiCk1rxDjB4DQmrUnB+LHv8npFYcYvQYEFLL34NYZkBIDYcYff5PSC2HGMsMCKlhBdHn/4TU8lHrZQaE1LCC6HOwJbXm5kYvU0pySpIPJflWkqNJvpDkDRO2PSPJp5I8keSpJDcnOXPqzkzIgJBacyeNXqZ3APhF4L3Az9J5N+eBJK8f1SjJHuBOYC+dF/5eBuwC7khy+lo6NI61lNSYxRCjGwKvpfOy3gPdbbcBLwE+SOft38O8CzgVOKeqvtlt+zk6bwh/D/COde9wlxWE1Mrc6GU6FwNPAJ/ubaiqAq4HXjpmuHAxcEsvHLptDwE3AZdM26FJGBBSa25+9DKds4D7qmqp2X5wxf7nSLIDOAO4Z8Dug8Ce7hBkJkbWUk9+9tpZXVddP3jeFSe6C88Lx+7+i4mPHTfESHJk7DmqdjabdgNfGXDo4RX7BzkVyIrjhrV9ZFyfpuEchNSoZGannnLfWttOzYCQGotLoz9vA6qDSRxicJWwq7seVCEAPE4nAKZpu2bOQUiNxRq9TOle4GXJc2Y593XXg+YYqKqjwIMMnqPYBzxaVTMZXoABIT1HVY1cpnQA2Alc1Gx/K/BAVd03pu2FSV7U25BkV/dcN07boUk4xJAaa6gSRrkZuA24LsluOs8wXA68Cnhj76AktwMXVNXKiZBrgLcANye5Clig87DVAnD1THrbZUBIjXFzENOoqkryJjof6KvpVBP30Xlw6qYxbb+d5Hw6QXEDncr/TuDVVfWNde/sCgaE1GgfVFgvVfUkcGV3GXbM/iHbv8qKSmOjGBBSY3FWCbEFGRBSY3H6icjvOQaE1DAf+gwIqWEF0WdASA3nIPoMCKmxNLuvNmw5BoTUsILoMyCkhnMQfQaE1JjFk5RblQEhNRxi9BkQUuP4kgnRY0BIjeMz+jrnVmRASI0lJymXGRBS47iTlMsMCKlx3FnKZQaE1HAKos+AkBpWEH0GhNRwDqLPgJAa3sXoMyCkhs9B9BkQUsMnKfsMCKmx5BzEMgNCajhJ2WdASI1j3uZcZkBIDX8Pos+AkBrHFqwgeny7t9Q4trA0ctloSU5Lcn2Sx5I8k+TOJOdN2PajSWrActck7a0gpMZmGmIkORm4FTgF+HXgEPBO4NYk51XV3ROc5mngwmbbU5Nc34CQGptsiPF24OXA2VX1JYAkdwBfpvOW8NdNcI7FqpqoYmgZEFLj2c0VEBcD/9ULB4CqejbJx4F3J/mBqpqoGpiGASE1xlUQSY6MO0dV7Vyn7pwF3DZg+0FgHngZ8Pkx5zglybeBFwD/B3wSeF9VPT3u4gaE1Nhk78XYDRwesP3wiv2j/CfwH8A9dALlQjpzGecneWVVHR/V2ICQGuMqiGmrgyT7GVwNDPLCqnqsd8lR3Rl1kqr6o2bTPyZ5APgz4BeAj41qb0BIjWMLi7M69f3A2yY8tjevcIjBVcKu7npQdTHOx4A/Bc7FgJBWZ1a3OavqYeCjq2x2L515iNY+YJFO6KxWuuuxs7E+KCU1nl1YGrlssAPAviQ/3tuQZDtwGfBPVfXkFOf8JTqf/bG3Pq0gpMYmew7iOuAK4MYkv01nSPEbwIuBn195YJKHAKpqb/fvHwZuAD4OfI3OJOVrgSuBzwF/Pe7iBoTU2ExPUlbVd5K8BvhD4MPAycCXgAur6otjmj8JPAa8GziNztDiQeADwAeqamHc9Q0IqbHJKoje3MVbJjhub/P348Ala7m2ASE1FjdZQJxIBoTUqM31oNQJZUBIDSuIPgNCaiz5s/fLDAip4a9a9xkQUmPJIcYyA0JqLPqr1ssMCKlRDjGWGRBSwwqiz4CQGosLVhA9BoTUcIjRZ0BIDYcYfQaE1PA2Z58BITWsIPoMCKnhHESfASE1FhfG/o7K84YBITWWFo6d6C5sGgaE1KjFmf3s/ZZjQEgNK4g+A0JqGBB9BoTUqCWHGD0GhNRYtIJYZkBIjaXjBkSPASE1HGL0GRBSw0nKPl/eKzWWFo6PXDZSkpcn+XCSzyf5TpJKsneV5zg7ya1JnknyeJK/SvJDk7Q1IKRGLS2OXDbYOcBFwMPAv622cZKXAbfTeS/nm4FfAV4B3J7klHHtHWJIjcXNNUl5Q1VdD5DkncBrVtn+KuAp4KKqeqZ7nnuAe+m8NfwPRjW2gpAaSwvHRi4bqaqm/u55km3AzwGf7IVD95z3A3cBl447hxWE1Bg3jEhyZOw5qnauU3fW4iXADuCeAfsOApePO4EBITWe/eKfZ9T+5CNHNqgra7W7uz48YN9hYEeSHVV1dNgJDAhplaatDpLsB26b8PAXVtVj01xngFG/gDPy13EMCGnj3A+8bcJjn1qH6x3qrncP2LcLOFpV3xl1AgNC2iBV9TDw0Q285IPAUeCsAfv2MXhu4rt4F0P6HlVVx4G/By5N8n297Ul+FDgXuHHcOawgpE2s+8F+fffPH+uuX5fkUeDRqrpjxbEPAVTV3hWneB/weeBvk1wDfD/w+8BDwLXjrm9ASJvbHuATzbY/6a7vAPaPalxV9yX5KToPRP0NcBz4DPCbVTV2nsOAkDaxqnqIzmPSkxy7d8j2f2f1T2ACzkFIGsGAkDSUASFpKANC0lAGhKShUuWLSiUNZgUhaSgDQtJQBoSkoQwISUMZEJKGMiAkDfX/u+sXm1D/+hAAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 288x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "heatmap(aligner_SF.Q_, figsize= (4,4), vmin=-1, vmax=1)\n",
    "aligner_SF.Q_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots(1, 1, figsize=(6, 6))\n",
    "ax.set_title(\"Simple rotation example, Sign Flips\")\n",
    "ax.scatter(X[:,0], X[:,1],\n",
    "           label=r\"$X$\", marker='x')\n",
    "ax.scatter(Y[:,0], Y[:,1],\n",
    "           label=r\"$Y$\", s=100, alpha=0.5)\n",
    "ax.scatter(X_prime_SF[:,0],\n",
    "           X_prime_SF[:,1],\n",
    "           label=r\"$X_{SF}$\", \n",
    "           marker='$F$')\n",
    "ax.set(xlim=(-1.20, 1.20), ylim=(-1.20, 1.20))\n",
    "ax.set_xticks([0])\n",
    "ax.set_yticks([0])\n",
    "ax.legend()\n",
    "ax.grid();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`SignFlips` correctly  brings $X$ to the third quadrant, yet the alignment is imperfect, as it is a heuristic-based method. Note that it does not assume that there is any sort of matching between the entries of $X$ and $Y$. Indeed, the two datasets need not even be of the same size."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This class can also be used to bring the dataset to the first orthant, if one provides the identity matrix as the second dataset."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### OrthogonalProcrustes\n",
    "\n",
    "`OrthogonalProcrustes` obtains $Q_{OP}$ by solving the classic orthogonal procrustes problem. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[Orthogonal Procrustes problem](https://en.wikipedia.org/wiki/Orthogonal_Procrustes_problem) is a matrix approximation problem in linear algebra, as one is asked to find a orthogonal matrix $Q$, which could most closely map the given matrix $X$ to another given matrix $Y$. Formally it seeks to find a matrix $Q_{OP}$ such that $|| X Q_{OP} - Y ||_F$ is minimized. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Since, this formulation strongly relies on the correspondence between the rows of the given matrices, this class can only be applied when the entery datasets $X$ and $Y$ have the equal shape ($n$, $d$), and the $i^{th}$ entry in $X$ is assumed to be the same value as vertex $i^{th}$ entry of $Y$, up to some noise. In graph setting, this means that the latent positions of the two graphs are equivalent."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`OrthogonalProcrustes` has a widely known closed form solution. Indeed, this class simply wraps  *[scipy.linal.orthogonal_procrustes()](https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.orthogonal_procrustes.html)*. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "from graspologic.align import OrthogonalProcrustes\n",
    "aligner_OP = OrthogonalProcrustes() \n",
    "X_prime_OP = aligner_OP.fit_transform(X, Y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that that $Q_{OP}$ is a generic orthogonal matrix, not a diagonal one."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.94924938, -0.31452442],\n",
       "       [ 0.31452442, -0.94924938]])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 288x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "heatmap(aligner_OP.Q_, figsize= (4, 4), vmin=-1, vmax=1)\n",
    "aligner_OP.Q_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots(1, 1, figsize=(6, 6))\n",
    "ax.set_title(\"Simple rotation example, OrthogonalProcrustes\")\n",
    "ax.scatter(X[:,0], X[:,1], label=r\"$X$\", marker='x')\n",
    "ax.scatter(Y[:,0], Y[:,1], label=r\"$Y$\", s=100, alpha=0.5)\n",
    "ax.scatter(X_prime_OP[:,0],\n",
    "           X_prime_OP[:,1],\n",
    "           label=r\"$X_{OP}$\", \n",
    "           marker='$O$')\n",
    "ax.set(xlim=(-1.20, 1.20), ylim=(-1.20, 1.20))\n",
    "ax.set_xticks([0])\n",
    "ax.set_yticks([0])\n",
    "ax.legend()\n",
    "ax.grid();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As expected, `OrthogonalProcrustes` obtains an exact solution when $X$ is a rotated copy of $Y$."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### SeedlessProcrustes\n",
    "\n",
    "`SeedlessProcrustes` is an algorithm that extends regular Procrustes to a case when there is no known correspondence between the entries. In fact, it can be used even when the number of entries between the two datasest is different."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Formally, if $X$ has $n$ entries, and $Y$ has $m$ entries, it tries to solve for an orthogonal matrix $Q_{SP}$, and an $n \\times m$ matrix $P$, with a special condition that rows sum to $1/m$, and columns sum to $1/n$, such that the quantity $|| X Q_{SP} - P Y ||_F$ is minimized."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Unlike the regular procrustes, this does not have a known closed form solution. `SeedlessProcrustes` tries to solve this optimization problem via an iterative algorithm that alternates optimal transport and regular procrustes. See the Notes section of the `SeedlessProcrustes` [references](https://graspy.neurodata.io/reference/align.html#seedless-procrustes) for more details on this algorithm."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "from graspologic.align import SeedlessProcrustes\n",
    "aligner_SP = SeedlessProcrustes() \n",
    "X_prime_SP = aligner_SP.fit_transform(X, Y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.94472887, -0.32785266],\n",
       "       [ 0.32785266, -0.94472887]])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 288x288 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "heatmap(aligner_SP.Q_, figsize=(4,4), vmin=-1, vmax=1)\n",
    "aligner_SP.Q_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots(1, 1, figsize=(6, 6))\n",
    "ax.set_title(\"SeedlessProcrustes, Simple rotation example\")\n",
    "ax.scatter(X[:,0], X[:,1], label=r\"$X$\", marker='x')\n",
    "ax.scatter(Y[:,0], Y[:,1], label=r\"$Y$\", s=100, alpha=0.5)\n",
    "ax.scatter(X_prime_SP[:,0],\n",
    "           X_prime_SP[:,1],\n",
    "           label=r\"$X_{SP}$\", \n",
    "           marker='$S$')\n",
    "ax.set(xlim=(-1.20, 1.20), ylim=(-1.20, 1.20))\n",
    "ax.set_xticks([0])\n",
    "ax.set_yticks([0])\n",
    "ax.legend()\n",
    "ax.grid();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Comparison between SignFlips, OrthogonalProcrustes, SeedlessProcrustes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The outcomes of three classes in simple rotation example together are plotted on the same figure in order to allow for a simpler comparison."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots(1, 1, figsize=(6, 6))\n",
    "ax.set_title(\"Aligning, Simple rotation example\")\n",
    "ax.scatter(X[:,0], X[:,1], label=r\"$X$\", marker='x')\n",
    "ax.scatter(Y[:,0], Y[:,1], label=r\"$Y$\", s=100, alpha=0.5)\n",
    "ax.scatter(X_prime_SF[:,0],\n",
    "           X_prime_SF[:,1], \n",
    "           label=r\"$X_{SF}$\",\n",
    "           marker='$F$')\n",
    "ax.scatter(X_prime_OP[:,0],\n",
    "           X_prime_OP[:,1], \n",
    "           label=r\"$X_{OP}$\", marker='$o$')\n",
    "ax.scatter(X_prime_SP[:,0],\n",
    "           X_prime_SP[:,1], \n",
    "           label=r\"$X_{SP}$\", marker='$S$')\n",
    "ax.set(xlim=(-1.20, 1.20), ylim=(-1.20, 1.20))\n",
    "ax.set_xticks([0])\n",
    "ax.set_yticks([0])\n",
    "ax.legend()\n",
    "ax.grid();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 1152x288 with 8 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, (ax1, ax2, ax3, ax4) = plt.subplots(1, 4, figsize = (16, 4))\n",
    "heatmap(Q, title=r'$Q$', vmin=-1, vmax=1, ax=ax1)\n",
    "heatmap(aligner_SF.Q_, title=r'$Q_{SF}$', vmin=-1, vmax=1, ax=ax2)\n",
    "heatmap(aligner_OP.Q_, title=r'$Q_{OP}$', vmin=-1, vmax=1, ax=ax3)\n",
    "heatmap(aligner_SP.Q_, title=r'$Q_{SP}$', vmin=-1, vmax=1, ax=ax4);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this simple example, `OrthogonalProcrustes` and `SeedlessProcrustes` align $X$ to $Y$ extremply well in terms of the Frobenius norm, whereas `SignFlips` can only do so well as to bring them to the same quadrant. In fact, when a dataset is a rotated copy of another - `OrthogonalProcrustes` aligns it up to a numerical epsilon precision."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Simple example\n",
      "Difference in Frobenious norm after Sign Flips  1.047909310874878\n",
      "Difference in Frobenious norm after Orthogonal Procrustes  5.800542824167306e-16\n",
      "Difference in Frobenious norm after Seedless Procrustes  0.046291889999320164\n"
     ]
    }
   ],
   "source": [
    "norm_SignFlips = np.linalg.norm(X_prime_SF - Y)\n",
    "norm_Orthogonal = np.linalg.norm(X_prime_OP - Y)\n",
    "norm_Seedless = np.linalg.norm(X_prime_SP - Y)\n",
    "print('Simple example')\n",
    "print('Difference in Frobenious norm after Sign Flips ', norm_SignFlips)\n",
    "print('Difference in Frobenious norm after Orthogonal Procrustes ', norm_Orthogonal)\n",
    "print('Difference in Frobenious norm after Seedless Procrustes ', norm_Seedless)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Shuffled Example"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Recall that unlike the other two methods, `OrthogonalProcrustes` heavily relies on a fact that the vertices of the two datasets are matched. Its performance will deteriorate even on this simple example if the vertices are shuffled, as shown in the following figure."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.utils import shuffle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_shuffled = shuffle(X)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "aligner_SF_shuffled = SignFlips()\n",
    "X_prime_SF_shuffled = aligner_SF_shuffled.fit_transform(X_shuffled, Y)\n",
    "aligner_OP_shuffled = OrthogonalProcrustes()\n",
    "X_prime_OP_shuffled = aligner_OP_shuffled.fit_transform(X_shuffled, Y)\n",
    "aligner_SP_shuffled = SeedlessProcrustes()\n",
    "X_prime_SP_shuffled = aligner_SP_shuffled.fit_transform(X_shuffled, Y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots(1, 1, figsize=(6, 6))\n",
    "ax.set_title(\"Aligning, Shuffled example\")\n",
    "ax.scatter(X_shuffled[:,0], X_shuffled[:,1], label=r\"$X$\", marker='x')\n",
    "ax.scatter(Y[:,0], Y[:,1], label=r\"$Y$\", s=100, alpha=0.5)\n",
    "ax.scatter(X_prime_SF_shuffled[:,0],\n",
    "           X_prime_SF_shuffled[:,1], \n",
    "            label=r\"$X_{SF}$\", marker='$F$')\n",
    "ax.scatter(X_prime_OP_shuffled[:,0],\n",
    "           X_prime_OP_shuffled[:,1], \n",
    "            label=r\"$X_{OP}$\", marker='$o$')\n",
    "ax.scatter(X_prime_SP_shuffled[:,0],\n",
    "           X_prime_SP_shuffled[:,1], \n",
    "            label=r\"$X_{SP}$\", marker='$S$')\n",
    "ax.set(xlim=(-1.20, 1.20), ylim=(-1.20, 1.20))\n",
    "ax.set_xticks([0])\n",
    "ax.set_yticks([0])\n",
    "ax.legend()\n",
    "ax.grid();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 1152x288 with 8 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, (ax1, ax2, ax3, ax4) = plt.subplots(1, 4, figsize = (16, 4))\n",
    "heatmap(Q, title=r'$Q$', vmin=-1, vmax=1, ax=ax1)\n",
    "heatmap(aligner_SF_shuffled.Q_, title=r'$Q_{SF}$', vmin=-1, vmax=1, ax=ax2)\n",
    "heatmap(aligner_OP_shuffled.Q_, title=r'$Q_{OP}$', vmin=-1, vmax=1, ax=ax3)\n",
    "heatmap(aligner_SP_shuffled.Q_, title=r'$Q_{SP}$', vmin=-1, vmax=1, ax=ax4);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this shuffled example, though the dataset $X_{shuffled}$ looks the same as dataset $X$ in the figure, the performance of `OthogonalProcrustes` is worse than the one in the simple rotation example above. This is because the value of $i^{th}$ entry in $X_{shuffled}$ is no longer corresponding with the $i^{th}$ entry of $Y$ after being shuffled from $X$."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Unmatched example"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As mentioned above, `SeedlessProcrustes` can be applied to two datasets with different number of entries. Consider the following example: $X$ is the same as previous, but the new $Y$ is a *different, larger* dataset, generated from the *same distribution*, and then subsequently rotated."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "Y_unmatched = np.random.uniform(0, 1, (30, 2)) @ Q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "aligner_SF_unmatched = SignFlips()\n",
    "X_prime_SF_unmatched = aligner_SF_unmatched.fit_transform(X, Y_unmatched)\n",
    "aligner_SP_unmatched = SeedlessProcrustes()\n",
    "X_prime_SP_unmatched = aligner_SP_unmatched.fit_transform(X, Y_unmatched)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots(1, 1, figsize=(6, 6))\n",
    "ax.set_title(\"Unmatched input example, Seedless Procrustes\")\n",
    "ax.scatter(X[:,0], X[:,1], label=r\"$X$\", marker='x')\n",
    "ax.scatter(Y_unmatched[:,0], Y_unmatched[:,1], label=r\"$Y$\", s=100, alpha=0.5)\n",
    "ax.scatter(X_prime_SF_unmatched[:,0],\n",
    "           X_prime_SF_unmatched[:,1],\n",
    "           label=r\"$X_{SF}$\", \n",
    "           marker='$F$')\n",
    "ax.scatter(X_prime_SP_unmatched[:,0],\n",
    "           X_prime_SP_unmatched[:,1],\n",
    "           label=r\"$X_{SP}$\", \n",
    "           marker='$S$')\n",
    "ax.set(xlim=(-1.20, 1.20), ylim=(-1.20, 1.20))\n",
    "ax.set_xticks([0])\n",
    "ax.set_yticks([0])\n",
    "ax.legend()\n",
    "ax.grid();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 864x288 with 6 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize = (12, 4))\n",
    "heatmap(Q, title=r'$Q$', vmin=-1, vmax=1, ax=ax1)\n",
    "heatmap(aligner_SF_unmatched.Q_, title=r'$Q_{SF}$', vmin=-1, vmax=1, ax=ax2)\n",
    "heatmap(aligner_SP_unmatched.Q_, title=r'$Q_{SP}$', vmin=-1, vmax=1, ax=ax3);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Mean of the dataset X:       [0.58510607 0.48290266]\n",
      "Mean of the dataset Y:       [-0.4035269 -0.6424252]\n",
      "Mean of the dataset X_{SF}:  [-0.58510607 -0.48290266]\n",
      "Mean of the dataset X_{SP}:  [-0.38535747 -0.65348582]\n"
     ]
    }
   ],
   "source": [
    "print(\"Mean of the dataset X:      \", np.mean(X, axis=0))\n",
    "print(\"Mean of the dataset Y:      \", np.mean(Y, axis=0))\n",
    "print(\"Mean of the dataset X_{SF}: \", np.mean(X_prime_SF_unmatched, axis=0))\n",
    "print(\"Mean of the dataset X_{SP}: \", np.mean(X_prime_SP_unmatched, axis=0))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`SeedlessProcrustes` is still able to align the distributions, while the `SignFlips` method is only a good heuristic. Note that `OthogonalProcrustes` is simply inapplicable in this context. "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
